/**********************************************************************
  项目名称/Project          : HUB08 模块驱动
  程序名称/Program name     : sketch_hub08.ino
  作者/Author               : xtbanban
  日期/Date（YYYYMMDD）     : 20230630
  程序目的/Purpose          : 驱动 hub08 64*16 LED板
***********************************************************************/
#include "env.h"

// 开发板类型
// #define _LoLin_
// 是否使用rtc芯片
// #define _RTC_

#include <EEPROM.h>
#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
#include <gpio.h>

// --------------------------------------------------------------------------------------------------------
// wifimanager can run in a blocking mode or a non blocking mode
// Be sure to know how to process loops with no delay() if using non blocking
bool wm_nonblocking = true;  // change to true to use non blocking

WiFiManager wm;                     // global wm instance
WiFiManagerParameter custom_field;  // global param ( for non blocking w params )
// --------------------------------------------------------------------------------------------------------

// --------------------------------------------------------------------------------------------------------
// These define's must be placed at the beginning before #include "ESP8266TimerInterrupt.h"
// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4
// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system.
#define _TIMERINTERRUPT_LOGLEVEL_ 0
//
// Select a Timer Clock
#define USING_TIM_DIV1 false   // for shortest and most accurate timer
#define USING_TIM_DIV16 false  // for medium time and medium accurate timer
#define USING_TIM_DIV256 true  // for longest timer but least accurate. Default
//
#include "ESP8266TimerInterrupt.h"  // 4.ESP8266TimerInterrupt
//
#define TIMER_INTERVAL_MS 10  // 10ms
//
// Init ESP8266 timer 1
ESP8266Timer ITimer;
// --------------------------------------------------------------------------------------------------------

#include "vari.h"  // 变量
#include "func.h"  // 函数
#include "time.h"  // 时间
#include "zimu.h"  //

void setup() {
  pinMode(LA, OUTPUT);
  pinMode(LB, OUTPUT);
  pinMode(LC, OUTPUT);
  pinMode(LD, OUTPUT);
  pinMode(EN, OUTPUT);
  pinMode(LAT, OUTPUT);
  pinMode(CLK, OUTPUT);
  pinMode(DATR1, OUTPUT);
  pinMode(DATR2, OUTPUT);
  pinMode(DATG1, OUTPUT);
  pinMode(DATG2, OUTPUT);

  // // 开机时，按住K3，清除设置
  // if (digitalRead(K3) == LOW) {
  //   delay(50);
  //   if (digitalRead(K3) == LOW) {
  //     wm.resetSettings();
  //     ESP.restart();
  //   }
  // }

  EEPROM.begin(10);  // 开启EEPROM，开辟10个位空间

  MyStyte3 = EEPROM.read(IAP_ADDRESS_STYTE3);
  WUXIU = EEPROM.read(IAP_ADDRESS_WUXIU) == '0' ? true : false;
  AUTOLIGHT = EEPROM.read(IAP_ADDRESS_AUTOLIGHT) == '0' ? true : false;
  LIGHT = EEPROM.read(IAP_ADDRESS_LIGHT) == '0' ? true : false;
  GREEN = EEPROM.read(IAP_ADDRESS_GREEN) == '1' ? true : false;

  if (MyStyte3 > STATE_MYSTYTE3_MAX)
    MyStyte3 = STATE_MYSTYTE3_BIGALL;

  MyLigth = STATE_MYLIGHT_4;                     // 默认亮度
  if (LIGHT) { MyLigth++; };                      // 设置了显示亮，亮度加一

  SetDisplay();

  ITimer.attachInterruptInterval(TIMER_INTERVAL_MS * 1000, flash10MS);  // 10ms定时器开启

  // =========================== wifi ====================================
  if (wm_nonblocking) wm.setConfigPortalBlocking(false);
  std::vector<const char*> menu = { "wifi", "sep" };  //"wifi", "param", "sep"
  wm.setMenu(menu);
  wm.setClass("invert");
  //
  WIFIOK = false;
  if (!wm.autoConnect("MyHUBAll-WiFi")) {
    F = 0;
    MyDisplay = STATE_MYDISPLAY_WIFI;  // 一直显示WIFI
    I_display = STATE_DISPLAY_WIFI_B;
  } else {
    WIFIOK = SetRTCTime();
    MyDisplay = STATE_MYDISPLAY_DEMO;  // 开机一次演示
    I_display = 0;                     // 演示显示第一行
  }
}

void loop() {
  bit r;
  // avoid delays() in loop when non-blocking and other long running code
  if (wm_nonblocking) wm.process();

  for (uchar i = 0; i < 17; i++) {  // 为程序中延时起效，增加一行16

    // ------------------------------- 提示 -------------------------------
    // - 使用ESP8266模块-CPU-80MHz，显示一行时间约为：400us，一场为：6.4ms  -
    // ------------------------------- 提示 -------------------------------

    r = true;
    if (!UpDown) {
      if (GREEN) {
        if (MyStyte3 == STATE_MYSTYTE3_BIGNYR) {
          if (i > 7 && i < 15) r = false;  //下方小字绿色
        }
      }
      if (MyLigth == 1) { digitalWrite(EN, HUB8_OE_ON); }  // 不显示 2 us , (2-5): 8 14 20 27
      SendDate(~XdataDisplayR[i][0], ~XdataDisplayR[i + 16][0], r);
      if (MyLigth == 6) { digitalWrite(EN, HUB8_OE_ON); }  // 不显示 48 us
      SendDate(~XdataDisplayR[i][1], ~XdataDisplayR[i + 16][1], r);
      if (MyLigth == 7) { digitalWrite(EN, HUB8_OE_ON); }  // 不显示 95 us
      SendDate(~XdataDisplayR[i][2], ~XdataDisplayR[i + 16][2], r);
      if (MyLigth == 8) { digitalWrite(EN, HUB8_OE_ON); }  // 不显示 142 us
      SendDate(~XdataDisplayR[i][3], ~XdataDisplayR[i + 16][3], r);
      if (MyLigth == 9) { digitalWrite(EN, HUB8_OE_ON); }  // 不显示 189 us
      SendDate(~XdataDisplayR[i][4], ~XdataDisplayR[i + 16][4], r);
      if (MyLigth == 10) { digitalWrite(EN, HUB8_OE_ON); }  // 不显示 236 us
      SendDate(~XdataDisplayR[i][5], ~XdataDisplayR[i + 16][5], r);
      if (MyLigth == 11) { digitalWrite(EN, HUB8_OE_ON); }  // 不显示 283 us
      SendDate(~XdataDisplayR[i][6], ~XdataDisplayR[i + 16][6], r);
      if (MyLigth == 12) { digitalWrite(EN, HUB8_OE_ON); }  // 不显示 330 us
      SendDate(~XdataDisplayR[i][7], ~XdataDisplayR[i + 16][7], r);

    } else {
      if (GREEN) {
        if (MyStyte3 == STATE_MYSTYTE3_BIGNYR) {
          if (i > 0 && i < 8) r = false;  //下方小字绿色
        }
      }
      if (MyLigth == 1) { digitalWrite(EN, HUB8_OE_ON); }  // 不显示 2 us , (2-5): 8 14 20 27
      SendDateF(~XdataDisplayR[16 - 1 - i + 16][7], ~XdataDisplayR[16 - 1 - i][7], r);
      if (MyLigth == 6) { digitalWrite(EN, HUB8_OE_ON); }  // 不显示 48 us
      SendDateF(~XdataDisplayR[16 - 1 - i + 16][6], ~XdataDisplayR[16 - 1 - i][6], r);
      if (MyLigth == 7) { digitalWrite(EN, HUB8_OE_ON); }  // 不显示 95 us
      SendDateF(~XdataDisplayR[16 - 1 - i + 16][5], ~XdataDisplayR[16 - 1 - i][5], r);
      if (MyLigth == 8) { digitalWrite(EN, HUB8_OE_ON); }  // 不显示 142 us
      SendDateF(~XdataDisplayR[16 - 1 - i + 16][4], ~XdataDisplayR[16 - 1 - i][4], r);
      if (MyLigth == 9) { digitalWrite(EN, HUB8_OE_ON); }  // 不显示 189 us
      SendDateF(~XdataDisplayR[16 - 1 - i + 16][3], ~XdataDisplayR[16 - 1 - i][3], r);
      if (MyLigth == 10) { digitalWrite(EN, HUB8_OE_ON); }  // 不显示 236 us
      SendDateF(~XdataDisplayR[16 - 1 - i + 16][2], ~XdataDisplayR[16 - 1 - i][2], r);
      if (MyLigth == 11) { digitalWrite(EN, HUB8_OE_ON); }  // 不显示 283 us
      SendDateF(~XdataDisplayR[16 - 1 - i + 16][1], ~XdataDisplayR[16 - 1 - i][1], r);
      if (MyLigth == 12) { digitalWrite(EN, HUB8_OE_ON); }  // 不显示 330 us
      SendDateF(~XdataDisplayR[16 - 1 - i + 16][0], ~XdataDisplayR[16 - 1 - i][0], r);
    }

    // 输出锁存 LAT:0->1
    digitalWrite(LAT, 0);
    digitalWrite(LA, i & 0x01);
    digitalWrite(LB, i & 0x02);
    digitalWrite(LC, i & 0x04);
    digitalWrite(LD, i & 0x08);
    digitalWrite(LAT, 1);

    if (MyLigth && i != 16) { digitalWrite(EN, !HUB8_OE_ON); }  // 增加的16一行不显示
  }

  // 没到每10ms，退出
  if (!TenMSec) { return; }
  TenMSec = false;

  // ================================= 每10ms，执行以下语句 =================================

  // 自动设置时间和亮度，在第一次显示时间之前操作，三个入口，显示完演示定时结束和主动按S键结束，显示模式转换结束后执行
  if (AutoSet) {
    AutoSet = false;

    AutoSetMyLigth(false);
  }

  if (MyDisplay) {
    if (MyDisplay == STATE_MYDISPLAY_WIFI || MyDisplay == STATE_MYDISPLAY_DEMO) {  // WIFI和演示
      if (tx_b_show) {
        tx_i_show_row++;         // 指针到下一行
        if (tx_i_show_row > 16)  // 特效显示时间160ms
        {                        // 指针最多16行，（一个字高16行）
          tx_b_show = false;     // 特效移动16行，结束特效
          tx_i_show_row = 0;
        }
      }
      SetDisplay();
    }

    return;  // 不再执行下面语句，退出
  }

  // 设置秒进度条 2-62
  H = (MyStyte3) ? l_tmpgetdate[0] + 2 : 0;

  if (SaveEPROM) {  // 保存EEPROM
    SaveEPROM = false;

    Save_EPROM();
  }

  static bit b;
  if (l_tmpgetdate[0] == 0) {  // 0秒时，执行一次
    if (b) {                   // 第一次进入，肯定是b=1，
      b = false;

      // 每0分钟或30分钟的0秒，执行一次（每半小时）：自动设置亮度
      if (l_tmpgetdate[1] == 0 || l_tmpgetdate[1] == 30) {
        AutoSetMyLigth(l_tmpgetdate[1] == 30);

        if (l_tmpgetdate[1] == 0 && NTPNOTOK) {
          GetNetworkTime();  // 联网异常的每小时更新一次
        } else if (l_tmpgetdate[1] == 0 && l_tmpgetdate[2] == 0) {
          GetNetworkTime();  // 否则，每天00:00:00更新一次
        }
      }
    }
  } else {
    b = true;
  }

  SetDisplay();
}
